﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Collections.ObjectModel;
using System.ComponentModel;

namespace ObjectFeatures
{
    public class Worker : INotifyPropertyChanged
    {
        private List<Timer> _timers = new List<Timer>();
        private List<Alarm> _alarms = new List<Alarm>();

        public List<Timer> Timers { get { return this._timers; } }
        public List<Alarm> Alarms { get { return this._alarms; } }

        public void StartTimer(Timer t) {
            t.StartTime = DateTime.Now;
            this._timers.Add(t);
            System.Diagnostics.Debug.WriteLine("Timer added {0}", t);
            if (this.PropertyChanged != null)
            {
                this._timers = new List<Timer>(this._timers);
                this.PropertyChanged(this, new PropertyChangedEventArgs("Timers"));
            }
        }
        public void AddAlarm(Alarm a) {
            if (a.RingTime <= DateTime.Now)
            {
                throw new ArgumentOutOfRangeException("a", "Cannot add an alarm to ring before now");
            }
            this._alarms.Add(a);
            if (this.PropertyChanged != null)
            {
                this._alarms = new List<Alarm>(this._alarms);
                this.PropertyChanged(this, new PropertyChangedEventArgs("Alarms"));
            }
        }

        private Thread _thread = null;
        private bool _running = false;

        public void Start()
        {
            if (_thread == null || !_thread.IsAlive)
            {
                this._thread = new Thread(this.Run);
                this._thread.Name = "Worker Thread";
                this._running = true;
                this._thread.Start();
            }
        }

        public void Stop() {
            this._running = false;
            if (this._thread.IsAlive) Thread.Sleep(500);
            if (this._thread.IsAlive)
            {
                this._thread.Interrupt();
            }
        }

        private void Run()
        {
            while (this._running)
            {
                int length, index;

                length = this._timers.Count;
                index = 0;
                while (index < length)
                {
                    Timer timer = this._timers[index];
                    TimeSpan diff = DateTime.Now.Subtract(timer.StartTime);
                    if (diff.TotalSeconds > timer.SecondsToWait)
                    {
                        timer.Finish();
                        System.Diagnostics.Debug.WriteLine("Timer finished");
                        this._timers.Remove(timer);
                        System.Diagnostics.Debug.WriteLine("Timer removed");
                        length--;
                        if (this.PropertyChanged != null)
                        {
                            this._timers = new List<Timer>(this._timers);
                            this.PropertyChanged(this, new PropertyChangedEventArgs("Timers"));
                        }
                    } else {
                        index++;
                    }
                }
                

                length = this._alarms.Count;
                index = 0;
                while (index < length)
                {
                    Alarm alarm = this._alarms[index];
                    if (alarm.RingTime <= DateTime.Now)
                    {
                        alarm.Finish();
                        this._alarms.Remove(alarm);
                        length--;
                        if (this.PropertyChanged != null)
                        {
                            this._alarms = new List<Alarm>(this._alarms);
                            this.PropertyChanged(this, new PropertyChangedEventArgs("Alarms"));
                        }
                    } else {
                        index++;
                    }
                }

                try
                {
                    Thread.Sleep(499);
                }
                catch (ThreadInterruptedException) { }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}
